#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>

#include "vicl.h"


void screen_init(void) 
{
    mainwnd = initscr();                                // init the screen handle
    noecho();
    cbreak();
    nodelay(mainwnd, TRUE);    
    start_color();                                      // init all colors
    init_pair(1, COLOR_WHITE, COLOR_BLUE);              // color pair #1 == white on blue
    init_pair(2, COLOR_RED, COLOR_BLUE);                // color pair #2 == red on blue
    wbkgd(screen, COLOR_PAIR(1));                       // set the active color scheme as white on blue
    refresh();                                          // flush the buffer to the screen
    wrefresh(mainwnd);                                  // flush the buffer to the window
    
    title_screen = newwin(1, SCR_WIDTH, 0, 0);
    box(title_screen, ACS_VLINE, ACS_HLINE);               // init the box
    wrefresh(title_screen);                                  // flush the buffer to the window
    
    info_screen = newwin(SCR_HEIGHT-1, SCR_WIDTH, 0, 0);
    box(info_screen, ACS_VLINE, ACS_HLINE);                 // init the box
    wrefresh(info_screen);                                  // flush the buffer to the window
    
    status_screen = newwin(1, SCR_WIDTH, SCR_HEIGHT-1, 0);
    box(status_screen, ACS_VLINE, ACS_HLINE);               // init the box
    wrefresh(status_screen);                                  // flush the buffer to the window
    
    error_screen = newwin(1, SCR_WIDTH, SCR_HEIGHT-1, 0);
    box(error_screen, ACS_VLINE, ACS_HLINE);                 // init the box
    wrefresh(error_screen);                                  // flush the buffer to the window
}

// Usage: vinix <hostname> <username> <password>
int main(int argc, char **argv)
{
    const char *hostname, *username, *password;
    jobHandle = VIX_INVALID_HANDLE;
    hostHandle = VIX_INVALID_HANDLE;
    
    if(argc < 4)
    {
        fprintf(stderr, "VINIX: Too few arguments\n");
        return -1;
    }
    
    screen_init();
    curs_set(0);
    VICL_INFO_RESET();

    VICL_STATUS("Initializing");

    hostname = argv[1]; // hostname
    username = argv[2]; // username
    password = argv[3]; // password
    
    // make sure the user-input is correct
    VICL_STATUS("Validating user input");
    if(validate_hostname(hostname))
        VICL_QUIT("Invalid hostname");
    
    // establish base connectivity
    VICL_STATUS("Connecting");
    if(setup_vmware_connection(hostname, username, password))
        VICL_QUIT("Connection failed");
    VICL_STATUS("Ready");


    // init our structures
    vmachine_idx = 0;
    int i;
    for(i = 0; i < MAX_VMS; i++)
    {
        vmachine[i].usable = false;
    }

    VICL_STATUS("Enumerating virtual machines");
    if(list_virtual_machines())
        VICL_QUIT("VM enumeration failed");
        
    vicl_info_help1();
    VICL_STATUS("Ready");

    while(1)
    {
        switch((keypress = getch()))
        {
            case 'q':
                VICL_QUIT("Exiting");
                return 0;
            
            case 'h':
                vicl_info_help1();
                VICL_TITLE("Main Menu");
                break;
               
            case 'l':
                VICL_STATUS("Listing virtual machines");
                list_virtual_machines();
                VICL_STATUS("Ready");
                VICL_TITLE("Main Menu");
                break;
            
            case 'p':
                VICL_STATUS("Enter the ID of a virtual machine to open");
                list_virtual_machines();
                VICL_TITLE("Main Menu");
                
                while((keypress = getch()) == -1){}
                    
                for(i = 0; i < MAX_VMS; i++)
                {
                    if(keypress == vmachine_ids[i])
                    {
                        if(vmachine[i].usable == true)
                        {
                            VICL_STATUS("Opening vmachine #%u", i);
                            if(open_virtual_machine(i) == -1)
                            {
                                VICL_ERROR("open_virtual_machine(%u) failed", i)
                                break;
                            }
                           
                            if(virtual_machine_power_options(i) == -1)
                            {   VICL_ERROR("virtual_machine_power_options(%u) failed", i);  break; }
                            else
                            {   VICL_STATUS("Ready");  }
                            break;
                        }
                    }
                }
                
                if(i >= MAX_VMS)
                {   
                    vicl_info_help1();
                    VICL_STATUS("Invalid ID");     
                }
                
                break;

            case 's':
                VICL_STATUS("Enter the ID of a virtual machine to open");
                list_virtual_machines();
                VICL_TITLE("Main Menu");
                
                while((keypress = getch()) == -1){}
                    
                for(i = 0; i < MAX_VMS; i++)
                {
                    if(keypress == vmachine_ids[i])
                    {
                        if(vmachine[i].usable == true)
                        {
                            VICL_STATUS("Opening vmachine #%u", i);
                            if(open_virtual_machine(i) == -1)
                            {
                                VICL_ERROR("open_virtual_machine(%u) failed", i)
                                break;
                            }
                           
                            VixPropertyID vcpus, vmem;
                            
                            vcpus = get_vm_vcpu_count(i);
                            vmem = get_vm_memory_size(i);

                            VICL_INFO_RESET();
                            VICL_TITLE("Virtual Machine System Information");
                            if(list_power_options(i) == -1)
                            {
                                VICL_ERROR("list_power_options(%u) failed", i)
                                break;  
                            }
                            VICL_INFO(" ");
                            VICL_INFO("Name: %s",  read_vm_variable(i, "displayName"));
                            VICL_INFO("Virtual hardware version: %s", read_vm_variable(i, "virtualHW.version"));
                            VICL_INFO("OS environment: %s", read_vm_variable(i, "guestOS"));
                            VICL_INFO("CPU count: %u", vcpus);
                            VICL_INFO("Memory: %uMB", vmem);
                            VICL_STATUS("Ready");
                            break;
                        }
                    }
                }
                
                if(i >= MAX_VMS)
                {   
                    vicl_info_help1();
                    VICL_STATUS("Invalid ID");     
                }
                
                break;
            
            case 't':
                VICL_STATUS("Enter the ID of a virtual machine to open");
                list_virtual_machines();
                VICL_TITLE("Main Menu");
                
                while((keypress = getch()) == -1){}
                    
                for(i = 0; i < MAX_VMS; i++)
                {
                    if(keypress == vmachine_ids[i])
                    {
                        if(vmachine[i].usable == true)
                        {
                            VICL_STATUS("Opening vmachine #%u", i);
                            if(open_virtual_machine(i) == -1)
                            {
                                VICL_ERROR("open_virtual_machine(%u) failed", i)
                                break;
                            }
                           
                            if(install_guest_vm_tools(i) == -1)
                            {   VICL_ERROR("install_guest_vm_tools(%u) failed", i);  break; }
                            else
                            {   VICL_STATUS("Ready");  }
                            break;
                        }
                    }
                }
                
                if(i >= MAX_VMS)
                {   
                    vicl_info_help1();
                    VICL_STATUS("Invalid ID");     
                }
                
                break;
            
            default:
                break;
        };
    }
    
    VICL_QUIT("Exiting");
    return 0;
}

